#include "AC33Mxxx_conf.h"



// UART
CSP_UART_T		* const 	UART0		= (CSP_UART_T *) UART0_BASE_ADDRESS; 
CSP_UART_T		* const 	UART1		= (CSP_UART_T *) UART1_BASE_ADDRESS; 
CSP_UART_T		* const 	UART2		= (CSP_UART_T *) UART2_BASE_ADDRESS; 
CSP_UART_T		* const 	UART3		= (CSP_UART_T *) UART3_BASE_ADDRESS; 


/**
*********************************************************************************************************
* @ Name : CSP_UART_ConfigureGPIO 
*
* @ Parameters
*		- uart : UART0~UART2
*
*
*********************************************************************************************************
*/
void CSP_UART_ConfigureGPIO (CSP_UART_T * const uart)
{

	if (uart == UART0)
	{
	
		//------------------------------------------------------------------------------------
		// UART0 (NORMAL)
		//
		//				PC14				RXD0
		//				PC15				TXD0
		//
		//				PCMR			@ address = 0x4000_1200
		//				PCCR			@ address = 0x4000_1204
		//
		//
		//------------------------------------------------------------------------------------
		CSP_PCU_ConfigureFunction (PCU_C, PIN_14, PC14_MUX_RXD0); 
		CSP_PCU_ConfigureFunction (PCU_C, PIN_15, PC15_MUX_TXD0); 
		
		CSP_PCU_Set_Direction_Type (PCU_C, PIN_14, PnCR_INPUT_LOGIC); 
		CSP_PCU_Set_Direction_Type (PCU_C, PIN_15, PnCR_OUTPUT_PUSH_PULL); 
		
		CSP_PCU_ConfigurePullup (PCU_C, PIN_14, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_C, PIN_15, PnPCR_PULLUP_DISABLE); 

	}
	else if (uart == UART1)
	{
		//------------------------------------------------------------------------------------
		// UART1 (NORMAL)
		//
		//				PC5				RXD1
		//				PC6				TXD1
		//
		//				PCMR			@ address = 0x4000_1200
		//				PCCR			@ address = 0x4000_1204
		//
		//
		//------------------------------------------------------------------------------------
		CSP_PCU_ConfigureFunction (PCU_C, PIN_5, PC5_MUX_RXD1); 
		CSP_PCU_ConfigureFunction (PCU_C, PIN_6, PC6_MUX_TXD1); 
		
		CSP_PCU_Set_Direction_Type (PCU_C, PIN_5, PnCR_INPUT_LOGIC); 
		CSP_PCU_Set_Direction_Type (PCU_C, PIN_6, PnCR_OUTPUT_PUSH_PULL); 
		
		CSP_PCU_ConfigurePullup (PCU_C, PIN_5, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_C, PIN_6, PnPCR_PULLUP_DISABLE); 

	}
	else if (uart == UART2)
	{
	
		//------------------------------------------------------------------------------------
		// UART2 
		//
		//				PD6				RXD2
		//				PD7				TXD2
		//
		//				PDMR			@ address = 0x4000_1300
		//				PDCR			@ address = 0x4000_1304
		//
		//
		//------------------------------------------------------------------------------------
		CSP_PCU_ConfigureFunction (PCU_D, PIN_6, PD6_MUX_TXD2); 
		CSP_PCU_ConfigureFunction (PCU_D, PIN_7, PD7_MUX_RXD2); 
		
		CSP_PCU_Set_Direction_Type (PCU_D, PIN_6, PnCR_OUTPUT_PUSH_PULL); 
		CSP_PCU_Set_Direction_Type (PCU_D, PIN_7, PnCR_INPUT_LOGIC); 
		
		CSP_PCU_ConfigurePullup (PCU_D, PIN_6, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_D, PIN_7, PnPCR_PULLUP_DISABLE); 
	}
	else if (uart == UART3)
	{
	
		//------------------------------------------------------------------------------------
		// UART2 
		//
		//				PB8				RXD3
		//				PB9				TXD3
		//
		//				PBMR			@ address = 0x4000_1100
		//				PBMR			@ address = 0x4000_1104
		//
		//
		//------------------------------------------------------------------------------------
		CSP_PCU_ConfigureFunction (PCU_B, PIN_8, PB8_MUX_RXD3); 
		CSP_PCU_ConfigureFunction (PCU_B, PIN_9, PB9_MUX_TXD3); 
		
		CSP_PCU_Set_Direction_Type (PCU_B, PIN_8, PnCR_INPUT_LOGIC); 
		CSP_PCU_Set_Direction_Type (PCU_B, PIN_9, PnCR_OUTPUT_PUSH_PULL); 
		
		CSP_PCU_ConfigurePullup (PCU_B, PIN_8, PnPCR_PULLUP_DISABLE); 
		CSP_PCU_ConfigurePullup (PCU_B, PIN_9, PnPCR_PULLUP_DISABLE); 
	}

}


/**
*********************************************************************************************************
* @ Name : CSP_UART_Init 
*
* @ Parameters
*		- uart : UART0~UART2
*		- property->u32Baudrate : 38400, 57600, 115200
*		   property->u16DataBits : 5, 6, 7, 8
*		   property->u8StopBits : 1, 2
*               property->u8Parity : 0, 1
*		   property->reference_clock : reference clock for baudrate
*
*
*********************************************************************************************************
*/
void CSP_UART_Init (CSP_UART_T * const uart, UART_PROPERTY *property)
{
	UINT32		mode; 



	//------------------------------------------------------------------------------
	// reset 
	//------------------------------------------------------------------------------



	//------------------------------------------------------------------------------
	// Line Control 
	//
	//				U0LCR			@ address = 0x4000_800C
	//				U1LCR			@ address = 0x4000_810C
	//				U2LCR			@ address = 0x4000_820C
	//				U3LCR			@ address = 0x4000_830C
	//
	//------------------------------------------------------------------------------
	// data bits
	switch (property->u16DataBits)
	{
	case 5:
		mode = UnLCR_DLEN_5_BITS;
		break; 

	case 6:
		mode = UnLCR_DLEN_6_BITS;
		break; 

	case 7:
		mode = UnLCR_DLEN_7_BITS;
		break;

	case 8:
	default:
		mode = UnLCR_DLEN_8_BITS;
		break;
	}

	// stop bit
	if (property->u8StopBits == 1)
	{
		mode |= UnLCR_STOPBIT_1_STOP_BIT; 
	}
	else if (property->u8StopBits == 2)
	{
		mode |= UnLCR_STOPBIT_2_STOP_BITS;
	}


	// parity 
	if (property->u8Parity == 1)
	{
		mode |= UnLCR_PARITY;
	}

	CSP_UART_SET_UnLCR(uart, mode); 





	//------------------------------------------------------------------------------
	// data control register
	//
	//				U0DCR			@ address = 0x4000_8010
	//				U1DCR			@ address = 0x4000_8110
	//				U2DCR			@ address = 0x4000_8210
	//				U3DCR			@ address = 0x4000_8310
	//
	//------------------------------------------------------------------------------
	CSP_UART_SET_UnDCR(uart, 0); 
	


	//------------------------------------------------------------------------------
	// baudrate
	//
	//				U0BDR			@ address = 0x4000_8020
	//				U1BDR			@ address = 0x4000_8120
	//				U2BDR			@ address = 0x4000_8220
	//				U3BDR			@ address = 0x4000_8320
	//
	//				U0BFR			@ address = 0x4000_8024
	//				U1BFR			@ address = 0x4000_8124
	//				U2BFR			@ address = 0x4000_8224	
	//				U3BFR			@ address = 0x4000_8324	
	//
	//------------------------------------------------------------------------------
	CSP_UART_SetBaudrate(uart, property->u32Baudrate, 2, property->u32Reference_clock);



	//------------------------------------------------------------------------------
	// inter-frame delay time 
	//
	//				U0IDTR			@ address = 0x4000_8030
	//				U1IDTR			@ address = 0x4000_8130
	//				U2IDTR			@ address = 0x4000_8230
	//				U3IDTR			@ address = 0x4000_8330
	//
	//------------------------------------------------------------------------------
	CSP_UART_SET_UnIDTR(uart, 9); 
	


	
	//------------------------------------------------------------------------------
	// FCR
	//
	//				16C450, 16C550
	//------------------------------------------------------------------------------
	//CSP_UART_SET_FCR(uart, 0); 			// 16C450 mode 


	//------------------------------------------------------------------------------
	// IER
	//
	//				RX, TX, Line, Modem interrupt 
	//------------------------------------------------------------------------------	
	//CSP_UART_SET_IER(uart, IER_DRIE); 			// Data Ready Interrupt 

}


/**
*********************************************************************************************************
* @ Name : CSP_UART_SetBaudrate 
*
* @ Parameters
*		- uart : UART0~UART2
*		- baudrate : 9600, 19200, 38400, 57600, 115200
*		- prescaler : 2
*		- ref_clk : reference clock for baudrate 
*
*
*********************************************************************************************************
*/
void CSP_UART_SetBaudrate (CSP_UART_T * const uart, UINT32 baudrate, UINT32 prescaler, UINT32 ref_clk)
{
	UINT32		numerator; 
	UINT32		denominator; 
	UINT32		bdr, bfr;
	UINT32		fd; 


	//------------------------------------------------------------------------------
	// numerator & denominator 
	//------------------------------------------------------------------------------
	numerator = ref_clk; 
	denominator = 16 * prescaler * baudrate; 


	//------------------------------------------------------------------------------
	// 	numerator 
	//	----------- = quotient (bdr) + fraction
	//	denominator
	//------------------------------------------------------------------------------
	bdr = numerator / denominator; 



	//------------------------------------------------------------------------------
	//	fraction x denominator = numerator - bdr x denominator
	//
	//	bfr = INT (fraction * 256) = ((f x d ) << 8) / d 
	//------------------------------------------------------------------------------

	fd = numerator - (bdr * denominator); 
	bfr = (fd << 8) / denominator; 


	CSP_UART_SET_UnBDR(uart, bdr); 
	CSP_UART_SET_UnBFR(uart, bfr); 


}



/**
*********************************************************************************************************
* @ Name : CSP_UART_Close 
*
* @ Parameters
*		- uart : UART0~UART2
*
*
*********************************************************************************************************
*/
void CSP_UART_Close (CSP_UART_T * const uart)
{
	// do nothing 
}


/**
*********************************************************************************************************
* @ Name : CSP_UART_TXEnable 
*
* @ Parameters
*		- uart : UART0~UART5
*
*
*********************************************************************************************************
*/
#if 0
void CSP_UART_TXEnable (CSP_UART_T * const uart)
{

}
#endif 

/**
*********************************************************************************************************
* @ Name : CSP_UART_RXEnable 
*
* @ Parameters
*		- uart : UART0~UART5
*
*
*********************************************************************************************************
*/
#if 0
void CSP_UART_RXEnable (CSP_UART_T * const uart)
{

}
#endif 


/**
*********************************************************************************************************
* @ Name : CSP_UART_TXDisable 
*
* @ Parameters
*		- uart : UART0~UART5
*
*
*********************************************************************************************************
*/
#if 0
void CSP_UART_TXDisable (CSP_UART_T * const uart)
{

}
#endif 


/**
*********************************************************************************************************
* @ Name : CSP_UART_RXDisable 
*
* @ Parameters
*		- uart : UART0~UART5
*
*
*********************************************************************************************************
*/
#if 0
void CSP_UART_RXDisable (CSP_UART_T * const uart)
{

}
#endif 




/**
*********************************************************************************************************
* @ Name : CSP_UART_ConfigureInterrupt 
*
* @ Parameters
*		- uart : UART0~UART2
*		- intr_mask
*		- enable : INTR_ENABLE, INTR_DISABLE
*
*
*********************************************************************************************************
*/
void CSP_UART_ConfigureInterrupt (CSP_UART_T * const uart, UINT32 intr_mask, UINT32 enable)
{
	volatile UINT32 	intr_status;
	volatile UINT32 	reg_val;
	


	//------------------------------------------------------------------------------
	// disable interrupt 
	//
	//				U0IER			@ address = 0x4000_8004
	//				U1IER			@ address = 0x4000_8104
	//				U2IER			@ address = 0x4000_8204
	//				U3IER			@ address = 0x4000_8304
	//
	//------------------------------------------------------------------------------
	CSP_UART_SET_UnIER(uart, (CSP_UART_GET_UnIER(uart) & ~UnIER_INTR_MASK)); 




	//------------------------------------------------------------------------------
	// clear interrupt flag 
	//
	//				U0IER			@ address = 0x4000_8004
	//				U1IER			@ address = 0x4000_8104
	//				U2IER			@ address = 0x4000_8204
	//				U3IER			@ address = 0x4000_8304
	//
	//------------------------------------------------------------------------------
	//
	//				line status		read LSR 
	//				RBR available		read RBR or IIR
	//				THR empty		write THR or read IIR
	//
	//------------------------------------------------------------------------------
	intr_status = CSP_UART_GET_UnIIR(uart) & UnIIR_INTR_MASK_NO_DMA; 

	if (intr_status & UnIIR_IID_LINE_STATUS)
	{
		reg_val = CSP_UART_GET_UnLSR(uart); 
	}

	if (intr_status & UnIIR_IID_RXBUF_READY)
	{
		reg_val = CSP_UART_GET_UnRBR(uart); 
	}


	
	//------------------------------------------------------------------------------
	// enable interrupt flag 
	//
	//				U0IER			@ address = 0x4000_8004
	//				U1IER			@ address = 0x4000_8104
	//				U2IER			@ address = 0x4000_8204
	//				U3IER			@ address = 0x4000_8304
	//
	//------------------------------------------------------------------------------
	if (enable == INTR_ENABLE)
	{
		CSP_UART_SET_UnIER(uart, (CSP_UART_GET_UnIER(uart) | intr_mask)); 
	}

	
}



